/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.inspur.edp.bef.bemanager.befexception.BeManagerException;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.json.model.BizEntityDeserializer;
import com.inspur.edp.bef.bizentity.json.model.BizEntitySerializer;
import com.inspur.edp.cef.designtime.api.element.GspAssociation;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonModel;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import com.inspur.edp.lcm.metadata.spi.MetadataTransferSerializer;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.swagger.models.RefModel;

import java.util.ArrayList;

/**
 * Json序列化 与前台交互
 */
public class TransferSerializer implements MetadataTransferSerializer {

    private String exceptionCode = "ContentSerializer";

    /**
     * json序列化
     *
     * @param metadataContent 元数据
     * @return 序列化后元数据
     */
    public final String serialize(IMetadataContent metadataContent) {

        GspBusinessEntity be = (GspBusinessEntity) ((metadataContent instanceof GspBusinessEntity) ? metadataContent : null);
        // 兼容关联子节点，RefObjectID,RefObjectCode,RefObjectName
        handleAssoRefObjectInfo(be);
        String eleJson;

        try {
            eleJson = getMapper().writeValueAsString(be);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("元数据序列化失败！", e);

        }
        return eleJson;
    }

    private ObjectMapper getMapper() {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(IGspCommonModel.class, new BizEntitySerializer());
        module.addDeserializer(IGspCommonModel.class, new BizEntityDeserializer());
        mapper.registerModule(module);
        return mapper;
    }
    ///#region 关联子节点

    private void handleAssoRefObjectInfo(GspBusinessEntity be) {

        ArrayList<IGspCommonElement> elementList = be.getAllElementList(false);
        if (elementList.size() > 0) {

            for (IGspCommonElement ele : elementList) {
                handleAssoRefObjectInfo(ele);
            }
        }
    }

    private void handleAssoRefObjectInfo(IGspCommonElement element) {
        if (element.getObjectType() == GspElementObjectType.Association && element.getChildAssociations() != null && element.getChildAssociations().size() > 0) {

            for (GspAssociation asso : element.getChildAssociations()) {
                if (CheckInfoUtil.checkNull(asso.getRefObjectID())) {
                    RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);

                    GspMetadata metadata = metadataService.getRefMetadata(asso.getRefModelID());

                    if (metadata.getContent() instanceof GspBusinessEntity) {
                        asso.setRefObjectID((((GspBusinessEntity) metadata.getContent()).getMainObject().getID()));
                        asso.setRefObjectCode(((GspBusinessEntity) metadata.getContent()).getMainObject().getCode());
                        asso.setRefObjectName(((GspBusinessEntity) metadata.getContent()).getMainObject().getName());
                    } else {
                        throw new BeManagerException("", exceptionCode, "无法加载关联业务实体'{asso.RefModelName}',ID='{asso.RefModelID}'。", null, ExceptionLevel.Info, false);
                    }
                }
            }
        }

    }

    ///#endregion

    /**
     * json反序列化
     *
     * @param contentString 需要反序列化元数据
     * @return 元数据
     */
    public final IMetadataContent deserialize(String contentString) {
        IMetadataContent content;
        try {
            content = (GspBusinessEntity) getMapper().readValue(contentString, GspBusinessEntity.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("元数据反序列化失败！");

        }
        return content;
    }
}
